#include "cTiledScene.h"
#include "Globals.h"
#include "utility.h"

cTiledScene::cTiledScene(void){
	tileSize = DEFAULT_TILE_SIZE;
	scenWidth = DEFAULT_SCENE_WIDTH;
	sceneHeight = DEFAULT_SCENE_HEIGHT;
	//blockSize = DEFAULT_BLOCK_SIZE;
}

cTiledScene::~cTiledScene(void){
}

void cTiledScene::InitFromIniFile(const char* pName, cData* Data, cCamera *Camera){
    string imageFile;
    string buffer;
    stringstream  iniFileName;
    if(strstr(pName, ".ini")==NULL){
        iniFileName << pName << ".ini";
    }else{
        iniFileName << pName;
    }

    ifstream inFileStream(iniFileName.str().c_str());
    if(!inFileStream.is_open()) {
          throw PECVJ2D_ERROR_FILE_NOT_FOUND;
    }

    while(getline(inFileStream, buffer)) {
        if(buffer[0]=='i' && buffer[5]=='F'){
            setImageFileName(buffer, imageFile);
        }else if(buffer[0]=='w'){
            setSceneDimension(buffer);
        }else if(buffer[0]=='h'){
            setSceneDimension(buffer);
        }else if(buffer[0]=='t' && buffer[1]=='i'){
            setTileSize(buffer);
        }else if(buffer[0]=='d' && buffer[4]=='F'){
            setDataFilename(buffer);
        }else if(buffer[0]=='d' && buffer[4]=='E'){
            setDataExtension(buffer);
        }else if(buffer[0]=='a' && buffer[1]=='n'){
            setAnimatedTile(buffer);
        }else if(buffer[0]=='b'){
            //setBlockSize(buffer);
        }
    }
    inFileStream.close();

    cTexture * img;
    if((img = Data->loadImage(imageFile, GL_RGBA))!=NULL){
        cScene::Init(img, Camera);
    }

    cTiledScene::Init();
}


/*
void cTiledScene::Init(cTexture* texture, cCamera* Camera){
    
}
 */

bool cTiledScene::LoadLevel(int level){
    int maxTileX;
    int tileY;
    int tileX;
    int p;
    string file;
    stringstream strstr;
    int fc=0, lc=0;
    char buffer[50];
    bool res;
    FILE *fd;
    int i,j,px,py;
    char tile;
    float coordx_tile, coordy_tile;
    int pot10=0;

    res=true;

    if(level<10){
        strstr << fileNameTiledConfig << "0" << level << "." << extensionFilenameTiledConfig;
        strstr >> file;
        //sprintf(file,"%s0%d%s", fileNameTiledConfig, level, extensionFilenameTiledConfig);
    }else{
        strstr << fileNameTiledConfig << level << "." << extensionFilenameTiledConfig;
        strstr >> file;        
        //sprintf(file,"%s%d%s", fileNameTiledConfig, level, extensionFilenameTiledConfig);
    }



    fd=fopen(file.c_str(),"r");
    if(fd==NULL) return false;

    //leer las propiedades del mapa
    //lc+= fgets(buffer+fc, 50-fc, fd);


    id_DL=glGenLists(1);
    glNewList(id_DL,GL_COMPILE);
    glBegin(GL_QUADS);

    for(j=sceneHeight-1;j>=0;j--){
        px=InitialOffsetX;
        py=InitialOffsetY+(j*tileSize);

        i=0;
        while(i<scenWidth){
                fscanf(fd,"%c",&tile);
                if(tile==',' || tile==';' || tile=='\n'){
                    sceneMap[(j*scenWidth)+i] = pot10;


                    if(pot10>0){
                        if(animatedFrameTileId.find(pot10)==animatedFrameTileId.end()){
                            maxTileX = this->GetTexture()->GetWidth()/tileSize;
                            tileY = (pot10-1)/maxTileX;
                            tileX = (pot10-1)%maxTileX;
                            float tfx = ((float)tileSize/(float)this->GetTexture()->GetWidth());
                            float tfy = ((float)tileSize/(float)this->GetTexture()->GetHeight());
                            coordx_tile = tileX*tfx;
                            coordy_tile = tileY*tfy;
                            /*
                            if(sceneMap[(j*scenWidth)+i]%2) coordx_tile = 0.0f;
                            else coordx_tile = 0.5f;
                            if(sceneMap[(j*scenWidth)+i]<3) coordy_tile = 0.0f;
                            else coordy_tile = 0.5f;
                             */

                            //BLOCK_SIZE = 24, FILE_SIZE = 64
                            // 24 / 64 = 0.375
                            glTexCoord2f(coordx_tile ,coordy_tile+tfy);
                            glVertex2i(px,py);
                            glTexCoord2f(coordx_tile+tfx,coordy_tile+tfy);
                            glVertex2i(px+tileSize,py);
                            glTexCoord2f(coordx_tile+tfx,coordy_tile);
                            glVertex2i(px+tileSize,py+tileSize);
                            glTexCoord2f(coordx_tile,coordy_tile);
                            glVertex2i(px,py+tileSize);

                        }else{
                            //crear animated item
                            animatedFrames.push_back(new cAnimatedVisibleItem());
                            animatedFrames.back()->SetFrameState(0);
                            animatedFrames.back()->SetFrameSeq(0);
                            animatedFrames.back()->SetNFrameStates(1);
                            animatedFrames.back()->SetFrameRate(20);
                            animatedFrames.back()->SetNTilesHor(
                                    this->GetTexture()->GetWidth()/this->GetTileSize());
                            animatedFrames.back()->SetNTilesVer(
                                    this->GetTexture()->GetHeight()/this->GetTileSize());
                            (animatedFrames.back()
                                    ->GetImageSequencesVector())->resize(1);
                            (*(animatedFrames.back()
                                    ->GetImageSequencesVector()))[0].resize(
                                                    animatedFrameTileId[pot10].size());
                            p=0;
                            for(list<int>::iterator it=animatedFrameTileId[pot10].begin();
                                                it!=animatedFrameTileId[pot10].end(); it++){
                                (*(animatedFrames.back()
                                    ->GetImageSequencesVector()))[0][p].resize(2);
                                maxTileX = this->GetTexture()->GetWidth()/tileSize;
                                tileY = ((*it)-1)/maxTileX;
                                tileX = ((*it)-1)%maxTileX;
                                (*(animatedFrames.back()
                                    ->GetImageSequencesVector()))[0][p][0]=tileX;
                                (*(animatedFrames.back()
                                    ->GetImageSequencesVector()))[0][p++][1]=tileY;
                            }
                            animatedFrames.back()->Init(GetTexture(),
                                                    px,
                                                    py,
                                                    0, 0, 0, 0);
                        }
                    }
                    px+=tileSize;

                    pot10=0;
                    i++;

                }else if(tile!=' '){
                    pot10*=10;
                    pot10+=tile-48;
                    //Tiles = 1,2,3,...
                }
      }
#ifdef _WIN32
            fscanf(fd,"%c",&tile); //pass enter
#else
            fscanf(fd,"%c",&tile); //pass enter
            if(tile!='\n'){
                fscanf(fd,"%c",&tile); //pass enter )
            }
#endif
    }

    glEnd();
    glEndList();

    fclose(fd);

    return res;
}

void cTiledScene::Draw(){
    cTexture*texture = GetTexture();
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture->GetID());
    glBegin(GL_QUADS);
    glCallList(id_DL);
    glDisable(GL_TEXTURE_2D);
    for(list<cAnimatedVisibleItem*>::iterator it=animatedFrames.begin();
                                            it!=animatedFrames.end(); it++){
        (*it)->Draw();
    }
}

vector<int>* cTiledScene::GetMap(){
	return &sceneMap;
}
int cTiledScene::GetTileSize() const {
    return tileSize;
}
int cTiledScene::GetSceneHeight() const {
    return sceneHeight;
}
int cTiledScene::GetScenWidth() const {
    return scenWidth;
}

void cTiledScene::Init(){
	sceneMap.resize(sceneHeight*scenWidth);
        LoadLevel(1);
}

void cTiledScene::setImageFileName(string iniValueLine, string &file){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    file = iniValueLine.substr(lpos, rpos-lpos);
}

void cTiledScene::setDataFilename(string iniValueLine){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    fileNameTiledConfig = iniValueLine.substr(lpos, rpos-lpos);
}

void cTiledScene::setDataExtension(string iniValueLine){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    extensionFilenameTiledConfig = iniValueLine.substr(lpos, rpos-lpos);
}


void cTiledScene::setSceneDimension(string iniValueLine){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    if(iniValueLine[0]=='w'){
        scenWidth=stringToint(iniValueLine.substr(lpos, rpos-lpos));
    }else{
        sceneHeight=stringToint(iniValueLine.substr(lpos, rpos-lpos));
    }
}

void cTiledScene::setTileSize(string iniValueLine){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    tileSize = stringToint(iniValueLine.substr(lpos, rpos-lpos));
}

void cTiledScene::setAnimatedTile(string iniValueLine){
    int posIni, pos, value, id;
    list<int> List;

    posIni=iniValueLine.find(CHAR_EQUAL)+1;
    for(pos=iniValueLine.find(":", posIni); pos!=iniValueLine.npos;
                                    posIni=pos+1, pos=iniValueLine.find(":", posIni)){
        value = stringToint(iniValueLine.substr(posIni, pos-posIni));
        List.push_back(value);
    }
    value = stringToint(iniValueLine.substr(posIni));
    List.push_back(value);

    id=List.front();

    if(animatedFrameTileId.find(id)==animatedFrameTileId.end()){
        animatedFrameTileId[id]= list<int>(List);
    }
}
